#pragma once

#include "Result.h"
#include "Task.h"
#include "Thread.h"
#include "poomodel.h"

#include <atomic>
#include <condition_variable>
#include <memory>
#include <queue>
#include <unordered_map>

const size_t THREAD_MAXTHRESHHOLD = 128;
const int THREAD_MAX_IDLE_TIME = 10; // 秒为单位
const size_t TASK_MAX_THRESHHOLD = 1024;

// 线程池:
//  固定模式下无需考虑线程安全，缓存模式需要考虑
class ThreadPool {
public:
  ThreadPool();
  ~ThreadPool();
  ThreadPool(const ThreadPool &) = delete;
  ThreadPool &operator=(const ThreadPool &) = delete;
  ThreadPool(ThreadPool&&) = delete;                 // 禁止移动构造
  ThreadPool& operator=(ThreadPool&&) = delete;      // 禁止移动赋值

  void setMode(PoolMode mode);
  void setTaskQueMaxThreshHold(size_t threshold);
  void setThreadSizeThreshHold(size_t threshold);
  std::shared_ptr<Result> submitTask(std::shared_ptr<Task> Tasksptr);
  void start(size_t initThreadSize = std::thread::hardware_concurrency());
private:
  void threadFunc(int threadID);
  bool checkRunningState() const;
private:
  std::unordered_map<int, std::unique_ptr<Thread>> threads_; // 线程列表
  size_t initThreadSize_{4};                     // 初始的线程数量
  std::atomic_int curThreadSize_{0}; // 正在运行的线程数; std::vector线程不安全
  std::atomic_int idleThreadSize_{0}; // 线程池中的空闲线程数
  size_t threadSizeThreshold_ {THREAD_MAXTHRESHHOLD}; // 线程数量上限
  // shared_ptr：允许调用方与线程池共享所有权，执行完自动释放，无需额外约定。
  // unique_ptr：调用方 std::move 进队列，线程池独占所有权；取出时再 std::move 转移到执行线程，执行完自动释放。
  // Task*: 把资源管理责任交给调用方;
  std::queue<std::shared_ptr<Task>> taskQue_; // 任务队列
  std::atomic_int taskSize_ {0};               // 任务数量
  size_t taskQueThreshHold_{TASK_MAX_THRESHHOLD}; // 任务队列数量上限阈值

  std::condition_variable notFull_;  // 任务队列不满, 可生产
  std::condition_variable notEmpty_; // 任务队列不空, 可消费
   std::condition_variable exitCond_; // 等待线程资源回收

  std::mutex taskQueMtx_; // 保证任务队列的线程安全

  PoolMode poolMode_ {PoolMode::MODE_FIXED}; // 当前线程池的工作模式
  std::atomic_bool isPoolRunning_ {false}; // 线程池运行状态
};